/*
 *
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package serverv2_0;
import java.io.*;
import java.net.*;
import java.util.*;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 *
 * @author suhui
 */

public class players{

	ArrayList<player> list = new ArrayList<player>();  // online list
	ArrayList<player> all  = new ArrayList<player>();   // all registered users
        ArrayList<player> toping = new ArrayList<player>();
    //int online = 0;

	//these attributes are needed for saving into txt file
    String filename="userInfo.txt";
    BufferedWriter bufferedWriter = null;


	
	// read all players from the text and save into arraylist, to be called by server at game start
    players(){

		createFile();
		System.out.println("\n");
		System.out.println("players() is visited");
		//System.out.println("\n");
		try{
			File f = new File(filename);
			FileInputStream fstream = new FileInputStream(f);
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;

			//Read File Line By Line
			while ((strLine = br.readLine()) != null) {

				StringTokenizer st	= new StringTokenizer(strLine);

				//here are where the strings are tokenized and saved
				String username		= st.nextToken();
				String password		= st.nextToken();
				int level		= Integer.parseInt(st.nextToken()) ;
				double experience	= Double.parseDouble(st.nextToken());

				// actual code to create new player and add to list
				player playerNew= new player();

				playerNew.username= username;
				playerNew.password= password;
				playerNew.level= level;
				playerNew.experience= experience;

				if(findplayer(username)==null)
				{
					all.add(  playerNew  );
					System.out.println(username+"                  is being copied from .txt file to ArrayList  ");
				}

			}
			in.close();
		}catch (Exception e){

		System.err.println("Error: " + e.getMessage());}
    }


	// user newly registered online , first save his name to online list, then to all list
    public boolean addnew(String name, String pw, InetAddress ip)
    {
        //System.out.println(name+pw);
        player newplayer = new player(name,pw,ip);
        if(findplayer(name) != null)
        {
            return false;
        }

        if(findonlineplayer(name)==null)
		{
                        list.add(newplayer);
			all.add(newplayer);
			
                        appendTxtFile(newplayer.username, newplayer.password, newplayer.level, newplayer.experience);
                        newplayer.online=true;
			System.out.println(name+ " added");
			
		}
		return true;
    }

    public int login(String name, String pw, InetAddress ip)
    {
        //player login = new player(name,pw,ip);
        player database = findplayer(name);
        if( database == null)
        {
            return 3;
        }
		else
        {
            boolean successful = database.comparepassword(pw);
            if(successful)
            {
                database.setip(ip);
                if(findonlineplayer(name)==null)
                    list.add(database);
                database.online = true;
                System.out.println(name+ " logged in");
                return 1;

            }
            else
                return 2;
        }

    }

    private player findplayer(String name)
    {
        for(int i = 0 ; i<all.size(); i++ )
        {
            if(name.equals((all.get(i)).username))
                return all.get(i);

        }
        return null;
    }

    private player findonlineplayer(String name)
    {
        for(int i = 0 ; i<list.size(); i++ )
        {
            if(name.equals((list.get(i)).username))
                return list.get(i);

        }
        return null;
    }

    public int number_online()
    {
        return list.size();
    }

    public String getonlinelist()
    {
        String construct = "type:data;\ndata_type:online_user_list;\n";
        construct = construct.concat("param:").concat(Integer.toString(number_online()) +";\n");

        for(int i = 0 ; i<list.size(); i++ )
        {
            construct = construct.concat((list.get(i)).username + " ");
            construct = construct.concat((list.get(i)).ipaddress + " ");
            construct = construct.concat(Integer.toString((list.get(i)).level)+ ";\n");
        }
        return construct;
    }

        


    

    public boolean addexperience(String user, int points)
    {
        player toadd = findplayer(user);

        if(toadd==null)
        {
            print("no such player");
            return false;
        }
        else
        {
            toadd.addexperience(points);
            toadd = findonlineplayer(user);
            if(toadd!= null)
            {
                toadd.experience += (double) points;
                toadd.getlevel();
            }
        }
        //save playerdata

        return true;
    }

    //NOT DONE
    public void pingall()
    {
        kickUnresponsive();

        for( int i = 0 ; i < list.size() ; i++ )
        {
            toping.add( list.get( i ));
        }

        for(int i = 0 ; i<list.size(); i++ )
        {
            ping(list.get(i));
        }
    }
    public void kickUnresponsive()
    {
        print("Removing " + toping.size() + " unresponsive players");
        for(int i = toping.size() -1 ; i >= 0 ;i--)
        {
            gooffline(toping.get(i).username);
        }
        toping.clear();
    }

    public void ping(player contact)
    {
        try {
            print("pinging " + contact.username);
            Socket clientSocket = new Socket(contact.ipaddress, 4000);
            DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());

            outToServer.writeBytes("type:command;action:ping;\n");
        } catch (Exception ex) {gooffline(contact.username);}
    }

    //
    public void gooffline(String user)
    {
        print(user + " not online");
        player notonline = findonlineplayer(user);
        if(notonline!=null)
            list.remove(notonline);
    }
    /***********************************
      * File writing functions
      ***********************************/
    // this method is to create a new txt
    public void createFile()
	{
		File file=new File(filename);
		if(!file.exists())  // if this file does not exist yet, create a new file
		{
			try
			{
				bufferedWriter = new BufferedWriter(new FileWriter(filename));
			} catch (FileNotFoundException ex)
			{ex.printStackTrace();} catch (IOException ex)
			{ex.printStackTrace();}

			finally
			{
	            //Close the BufferedWriter
	            try
				{
	                if (bufferedWriter != null)
					{
	                    bufferedWriter.flush();
	                    bufferedWriter.close();
						System.out.println("new file has been created");
	                }
	            } catch (IOException ex)
				{ ex.printStackTrace();}
			}

		}
	}  // end of createfile()


	//this method appends a line to userInfo.txt file
    public void appendTxtFile(String name, String password, int level, double experience)
	{
		try
		{
			boolean append = true;
			FileWriter fw = new FileWriter(filename,append);
			
                        fw.write(name);
			fw.write(" ");
			fw.write(password);
			fw.write(" ");
			fw.write(Integer.toString(level));
			fw.write(" ");
			fw.write( Double.toString(experience) );
			fw.write("\r\n");
			fw.close();
		}
		catch(IOException ioe)
		{
			System.err.println("IOException: " + ioe.getMessage());
		}

	}//end of appendTxtFile()


	// this method finds every all ArrayList element, save into txt by calling appendTxtFile
    public void  exportAll()
    {
		System.out.println("\n");
		for (int i=0;i< all.size(); i++)
		{
			appendTxtFile(all.get(i).username, all.get(i).password, all.get(i).level, all.get(i).experience);
			System.out.println(all.get(i).username+ "                 is being saved from all.get( "+i+" ) to .txt file");
		}
		System.out.println("\n");
		System.out.println("at export all, all.size()= "+all.size());
    }


    //call this before closing, delete the exisiting txt, create a new txt with same name and fill up
	//with new ArrayList info
    public void clearAndExport()
    {
		System.out.println("\n");
                File file=new File(filename);
                file.delete();
		System.out.println("old file has been deleted");
                createFile();
                exportAll();

		System.out.println("\n");
		System.out.println("exportAll() has been called");
    }
public void removeLineFromFile(String lineToRemove) {

        try {

          File inFile = new File(filename);

          if (!inFile.isFile()) {
            System.out.println("Parameter is not an existing file");
            return;
          }

          //Construct the new file that will later be renamed to the original filename.
          File tempFile = new File(inFile.getAbsolutePath() + ".tmp");

          BufferedReader br = new BufferedReader(new FileReader(filename));
          PrintWriter pw = new PrintWriter(new FileWriter(tempFile));

          String line = null;

          //Read from the original file and write to the new
          //unless content matches data to be removed.
          while ((line = br.readLine()) != null)
          {

            if (!line.trim().equals(lineToRemove))
            {
              pw.println(line);
              pw.flush();
            }

          }

          pw.close();
          br.close();

          //Delete the original file
          if (!inFile.delete()) {
            System.out.println("Could not delete file");
            return;
          }

          //Rename the new file to the filename the original file had.
          if (!tempFile.renameTo(inFile))
            System.out.println("Could not rename file");

        }
        catch (FileNotFoundException ex) {
          ex.printStackTrace();
        }
        catch (IOException ex) {
          ex.printStackTrace();
        }
      }
public void updateplayer(String name, int newlevel, double newexperience)
    {
       System.out.println("\n");
		System.out.println("players() is visited");
		//System.out.println("\n");
		try{
			File f = new File(filename);
			FileInputStream fstream = new FileInputStream(f);
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
                        String lineToRemove=null;

			//Read File Line By Line
			while (br.ready()) {
                                strLine = br.readLine();
                                lineToRemove=strLine;
				StringTokenizer st	= new StringTokenizer(strLine);

				//here are where the strings are tokenized and saved
				String username		= st.nextToken();
				String password		= st.nextToken();
				int level		= Integer.parseInt(st.nextToken()) ;
				double experience	= Double.parseDouble(st.nextToken());

				// actual code to create new player and add to list

				if(username.equals(name))
				{
                                        in.close();
                                        removeLineFromFile(lineToRemove);
                                        appendTxtFile(username, password, newlevel,newexperience);
                            }
                                
                        }

                     }

		catch (Exception e){

		System.err.println("Error: " + e.getMessage());}
    }



    /***********************************
      * Random Functions
      ***********************************/
    void print(String toprint)
    {
         System.out.println(toprint);
     }

     /***********************************
      * Player class
      ***********************************/
    public class player{

        public String username = "";
        String password = "";
        public String ipaddress = "";

        public double experience = 0;
        public int level = 0;
        public boolean online = false;

        //for testing purposes
        public player() {
            username = "superman";
            password = "notaplane";
            ipaddress = "localhost";
        }

        public player(String name, String pw, InetAddress ip)
		{
            username = name;
            password = pw;
            ipaddress = ip.getHostAddress();
        }

        public void setip(InetAddress ip)
        {
            ipaddress = ip.getHostAddress();
        }

        public boolean comparepassword(String input)
        {
            if(password.equals(input))
            {
                return true;
            }
            return false;
        }

        public int getlevel()
        {
            double newlevel = experience/1000;
            level = (int)newlevel;
            return level;
        }

        public double getexperience()
        {
            return experience;
        }

        public double addexperience(double points)
        {
            experience += points;
            getlevel();
            updateplayer(this.username,  this.level, this.experience);
            return experience;
        }
	}



	public static void main (String args[])
	{
		//System.out.println("about to call players() ------------");
		//new players();
		//System.out.println("-------just finished calling players() ");
		//new players().addnew("lubin", "6hdh24lk..2!!@@#",123,134);
		new players().appendTxtFile("666wme","lkaj293",8,9);
		//new players().clearAndExport();

		System.out.println("\n");

		new players().clearAndExport();
		System.out.println("-------here is end of main() ------------");
                new players().updateplayer("fa", 0, 0);
                new players().clearAndExport();
                new players().clearAndExport();
                new players().clearAndExport();
		return;
	}

}